<?php
namespace App\Tools;
class Tools
{
    /**
     * @param string $action 发送指令。例如：regist,login,confirm, 与/config/sms.php里面的templates的键名匹配
     * @param string $mobile 手机号
     * @param array $data 模板中的变量，例如：['code'=>'156879']
     * @param bool $isCode 是否为验证码类型，是将缓存5分钟
     * @return array|\Illuminate\Http\JsonResponse
     * @throws \Psr\SimpleCache\InvalidArgumentException
     */
    function send_sms(string $action,string $mobile,array $data,bool $isCode=false)
    {
        $config=config("easysms");
        $easySms = new \Overtrue\EasySms\EasySms($config);
        if(isset($config['templates'][$action])){
            $template_code=$config['templates'][$action]['template_code'];
            $content=$config['templates'][$action]['content'];
            foreach($data as $k=>$v){//替换变量
                $content=str_ireplace('${'.$k.'}',$v,$content);
            }
            try{

                $res= $easySms->send($mobile, [
                    'content'  => $content,
                    'template' => $template_code,
                    'data' =>$data,
                ]);

                if($res&&$isCode&&isset($data['code'])){
                    \App\Models\MobileSms::insert([
                        'action'=>$action,
                        'mobile'=>$mobile,
                        'code'=>$data['code'],
                        'content'=>$content,
                        'created_at'=>date('Y-m-d H:i:s'),
                        'expire_at'=>date('Y-m-d H:i:s',time()+300),
                    ]);
                    //cache()->set("sms_".$action."_".$mobile,$data['code'],300);
                }
                save_log('api','test',$res);
            }catch(\Exception $e){
                $msg='发送失败';
                $errors=$e->getMessage();
                save_log('daily','短信发送失败:'.$mobile,[$action,$data]);
                if(isset($errors['aliyun'])&&isset($errors['aliyun']['raw']['Message'])){
                    $msg=$errors['aliyun']['raw']['Message'];
                }
                return ['code'=>500,'msg'=>$msg];
            }
            return ['code'=>200,'msg'=>'发送成功'];
        }else{
            return ['code'=>500,'msg'=>"未找到短信模板"];
        }
    }
    public static function check_sms_code(string $action,string $mobile,string $code=null): bool
    {
        $cacheCode=cache()->get("sms_".$action."_".$mobile);
        $sms=\App\Models\MobileSms::where('mobile',$mobile)->where('action',$action)->orderByDesc('id')->selectRaw('id,mobile,code,status,expire_at')->first();
        if(empty($sms))return false;
        if($sms->status!=0||strtotime($sms->expire_at)<time())return false;
        if($sms->code===$code){
            $sms->status=1;
            $sms->save();
            return true;
        }else{
            return false;
        }
    }
    /**
     * 是否是 手机访问
     * @return bool
     */
    function in_mobile() {
        // 如果有HTTP_X_WAP_PROFILE则一定是移动设备
        if (isset($_SERVER['HTTP_X_WAP_PROFILE'])) {
            return true;
        }
        // 如果via信息含有wap则一定是移动设备,部分服务商会屏蔽该信息
        if (isset($_SERVER['HTTP_VIA'])) {
            // 找不到为flase,否则为true
            return stristr($_SERVER['HTTP_VIA'], "wap") ? true : false;
        }
        // 脑残法，判断手机发送的客户端标志,兼容性有待提高。其中'MicroMessenger'是电脑微信
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            $clientkeywords = array('nokia','sony','ericsson','mot','samsung','htc','sgh','lg','sharp','sie-','philips','panasonic','alcatel','lenovo','iphone','ipod','blackberry','meizu','android','netfront','symbian','ucweb','windowsce','palm','operamini','operamobi','openwave','nexusone','cldc','midp','wap','mobile','MicroMessenger');
            // 从HTTP_USER_AGENT中查找手机浏览器的关键字
            if (preg_match("/(" . implode('|', $clientkeywords) . ")/i", strtolower($_SERVER['HTTP_USER_AGENT']))) {
                return true;
            }
        }
        // 协议法，因为有可能不准确，放到最后判断
        if (isset ($_SERVER['HTTP_ACCEPT'])) {
            // 如果只支持wml并且不支持html那一定是移动设备
            // 如果支持wml和html但是wml在html之前则是移动设备
            if ((strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') !== false) && (strpos($_SERVER['HTTP_ACCEPT'], 'text/html') === false || (strpos($_SERVER['HTTP_ACCEPT'], 'vnd.wap.wml') < strpos($_SERVER['HTTP_ACCEPT'], 'text/html')))) {
                return true;
            }
        }
        return false;
    }
    /**
     *  递归属性结构
     * @author MrGuo
     * @date   2020-12-19
     * @param  array        $son   [二维数组，主键名是id]
     * @param  boolean|null $alone [是否返回没有找到上级的, 默认返回]
     * @return [array]             [N维数组，children是子集，level表示第几级]
     */
    public static function  children_tree(array $son = [], string $field = "pid", bool $alone = null) {
        $father = [];
        foreach ($son as $key => $val) {
            if (intval($val[$field]) == 0) {
                //获取第一代
                array_push($father, $val);
                unset($son[$key]);
            }
        }
        foreach ($father as $key => $val) {
            $father[$key] = self::children($val, $son, 0);
        }
        if ($alone) {
            //保留没有父级的孤儿
            foreach ($son as $key => $val) {
                array_push($father, $val);
            }
        }
        return $father;
    }
    public static function children(array $father = [], array $son = [], int $level = 0, string $field = "pid") {
        $father['children'] = array();
        foreach ($son as $k => $v) {
            if (intval($v[$field]) == intval($father['id'])) {
                $sons = __Children($v, $son, $level + 1, $field); //递归，把一个系先全部找完。
                array_push($father['children'], $sons);
                unset($son[$k]);
            }
        }
        $father['level'] = $level;
        return $father;
    }

    /**
     * 数字装换汉字，例如：25 转换 成二十五
     * @param int $num
     * @return string
     */
    public static function number2chinese($num): string
    {
        if (is_int($num) && $num < 100) {
            $char = array('零', '一', '二', '三', '四', '五', '六', '七', '八', '九');
            $unit = ['', '十', '百', '千', '万'];
            $return = '';
            if ($num < 10) {
                $return = $char[$num];
            } elseif ($num%10 == 0) {
                $firstNum = substr($num, 0, 1);
                if ($num != 10) $return .= $char[$firstNum];
                $return .= $unit[strlen($num) - 1];
            } elseif ($num < 20) {
                $return = $unit[substr($num, 0, -1)]. $char[substr($num, -1)];
            } else {
                $numData = str_split($num);
                $numLength = count($numData) - 1;
                foreach ($numData as $k => $v) {
                    if ($k == $numLength) continue;
                    $return .= $char[$v];
                    if ($v != 0) $return .= $unit[$numLength - $k];
                }
                $return .= $char[substr($num, -1)];
            }
            return $return;
        }else{
            return '';
        }
    }
    /**
     * 二位数组重新排序
     * @param array $array 数组
     * @param string $k1 要排序的字段
     * @param int $sort 排序方式：3降序，4升序    参考：https://php.net/manual/en/array.constants.php
     * @param string|null $k2 要排序的字段2（可选）
     * @param int $sort2 排序方式2：3降序，4升序   参考：https://php.net/manual/en/array.constants.php
     * @return array
     */
    public static function array_sort_by(array $array, string $k1, int $sort = SORT_DESC, string $k2=null, int $sort2=SORT_DESC) {
        $args = func_get_args();
        if(empty($args)){
            return null;
        }
        $arr = array_shift($args);
        if(!is_array($arr)){
            throw new Exception("第一个参数不为数组");
        }
        foreach($args as $key => $field){
            if(is_string($field)){
                $temp = array();
                foreach($arr as $index=> $val){
                    $temp[$index] = $val[$field];
                }
                $args[$key] = $temp;
            }
        }
        $args[] = &$arr;//引用值
        call_user_func_array('array_multisort',$args);
        return array_pop($args);
    }
    /**
     * 腾讯地图获取坐标点位置,1对多
     * @param float $latitude 起点纬度
     * @param float $longitude 起点经度
     * @param array $points 所有终点坐标，[['latitude'=>30.213123784,'longitude'=>'108.23861873']]
     * @param string $mode 导航方式，driving：驾车，walking：步行 ，bicycling：自行车
     * @return array $result 返回二维数组
     */
    public static function distance_api(float $latitude,float $longitude,array $points,string $mode='walking'): array
    {
        $to=[];
        $result=[];
        foreach($points as $k=>$v){
            $to[]=$v['latitude'].",".$v['longitude'];
            $result[$k]=[
                'distance'=>null,
                'duration'=>null,
                //表示从起点到终点的结合路况的时间，秒为单位
                //注：步行/骑行方式（不计算耗时）以及起终点附近没有道路造成无法计算时，不返回本此节点
            ];
        }
        $to=implode(';',$to);
        $url="https://apis.map.qq.com/ws/distance/v1/matrix/?mode={$mode}&from={$latitude},{$longitude}&to={$to}&key=".env("TENCENT_MAP_API_KEY");

        try{
            $res=curl_get($url);

            $result=$res['result']['rows'][0]['elements'];
            return $result;
        }catch(\Exception $e){
            return $result;
        }
    }
    /**
     * 生成MySQL坐标距离字段
     * @param string $latitude 起点纬度
     * @param string $longitude 起点经度
     * @param string $field_lat 目标纬度字段
     * @param string $field_long 目标经度地段
     * @param string $alias 新字段别名
     * @return string
     */
    public function distance_line_raw(?string $latitude=null,?string $longitude=null,string $field_lat='latitude',string $field_long='longitude',string $alias="distance"){
        if(empty($latitude)||empty($longitude))return "0 as distance";
        if(!(floatval($latitude)>0&&floatval($longitude))){
            throw new \Exception('参数错误');
        }
        $longitude = preg_replace('/[^0-9.,-]/', '', $longitude);
        $latitude = preg_replace('/[^0-9.,-]/', '', $latitude);
        return "round(st_distance_sphere(point($field_long,$field_lat),point({$longitude},{$latitude})),0) as ".($alias?$alias:'distance');
    }
    function replace_script(string $str=null){
        if(empty($str))return $str;
        return str_ireplace('script','',strip_tags($str,'<script>'));
    }

    /**
     * 隐藏手机号中间4位
     * @param string $mobile
     * @return string
     */
    public static function hide_mobile(string $mobile){
        return mb_substr($mobile,0,3)."****".mb_substr($mobile,7,11);
    }
    /**
     * 将二维数组转为一维键值对数组
     * @param array $array
     * @param string $label
     * @param string $id
     * @return array
     */
    public static function pluck_array(array $array,string $label="name",string $id='id'){
        $pluckList=[];
        foreach($array as $v){
            if(isset($v[$id])&&isset($v[$label])){
                $pluckList[$v[$id]]=$v[$label];
            }
        }
        return $pluckList;
    }

}
